Skip to content

feat: add optional --summaries semantic layer for PR deltas - #14

Merged
diegomarino merged 1 commit into
mainfrom
feat/semantic-summaries
Jul 10, 2026
Merged

feat: add optional --summaries semantic layer for PR deltas#14
diegomarino merged 1 commit into
mainfrom
feat/semantic-summaries

Conversation

@diegomarino

Copy link
Copy Markdown
Owner

Why

A downstream consumer (batutas) runs a fail-closed merge gate needing semantic facts — ciRollup === 'green', mergeable, unresolvedThreads === 0. The v0.2 per-delta to fingerprint can't supply them: ci/review/reviews are opaque change-detection digests (--detail marks them opaque: true). Correct for "did CI change?", useless for "is CI green?" — forcing consumers into a second GitHub fetch.

What

--summaries attaches an optional, normalized delta.summary to every PR delta with an observed to state, derived purely from the same observation that produced the fingerprints (no second fetch):

"summary": {
  "ciRollup": "green|failed|pending|none",   // zero checks ⇒ none, never green
  "reviewDecision": "approved|changes_requested|review_required|none",
  "mergeable": "mergeable|conflicting|unknown",  // honest tri-state, not a boolean
  "state": "open|closed|merged",
  "isDraft": false,
  "unresolvedReviewThreads": 0,
  "headSha": "<40-hex>"
}

Design invariants

  • Sibling delta.summary, never nested in to. deltaIdentity() hashes only to/from/classes/missingTicks, so the content-addressed delta.id and the whole report body stay byte-identical whether or not the flag is set. Existing consumers see zero diff.
  • Zero checks ⇒ ciRollup: 'none', never 'green' — fail-closed gates decide what "no CI" means. Precedence: failed > pending > green. Classification keys on both status and conclusion, so an in-progress {status:'IN_PROGRESS', conclusion:''} CheckRun is pending, not green.
  • Honest enums, not booleans. mergeable:'unknown' / reviewDecision:'none' preserve GitHub's tri-state / not-yet-computed truth (merged PRs legitimately report unknown).
  • schemaVersion stays 1 per the repo's additive-never-bumps policy. Only --help-json grows (deltaSummaryFields/deltaSummaryEnums).
  • Mirrored onto the outpost webhook payload under the same flag.

Testing

TDD against real captured GraphQL payloads (test/fixtures/summaries/, recorded from live PRs on 2026-07-11) run through the real fetchPRs → normalizePr → prFingerprint → prSummary path, covering none (nodejs/node#64097), green (this repo #12), pending (nodejs/node#63949, real in-progress CheckRun), failed (react/react#36863). Plus CLI acceptance (none→green ci-changed, additive byte-stability) and --help-json schema tests. 211 tests pass; lint + prettier clean.

Acceptance

  • No-checks PR ⇒ ciRollup: 'none'; a green status ⇒ ci-changed delta with summary.ciRollup: 'green'
  • Existing consumers (no flag) see zero diff (delta.id + all fields byte-identical)
  • README + docs/contract.md document the schema precisely enough to build a Zod/JSON-Schema validator (also machine-readable via gh-delta/contract and --help-json)

Validated with a Codex blind-debate peer review (classification table checked against live GitHub enums; three scope gaps — outpost propagation, DELTA_FIELDS exhaustiveness test, in-progress fixture coverage — folded in).

Version bump is release-please-owned: this feat: will drive 0.2.0 → 0.3.0.

Derive typed, normalized semantic facts (ciRollup, reviewDecision, mergeable,
state, isDraft, unresolvedReviewThreads, headSha) from the SAME observation that
produces the opaque change-detection fingerprints, so a fail-closed consumer can
read the observed semantic PR state without a second GitHub fetch.

- ciRollup: green|failed|pending|none. A PR with ZERO checks is 'none', never
  'green', so fail-closed gates decide what no-CI means; fail-closed precedence
  is failed > pending > green.
- Sibling delta.summary (never nested in `to`): delta.id and the report body are
  byte-identical whether or not --summaries is set, so existing consumers see
  zero diff; schemaVersion stays 1 per the additive-never-bumps policy.
- mergeable and reviewDecision kept as honest enums (unknown / none) rather than
  collapsed to booleans, preserving GitHub's tri-state / not-yet-computed truth.
- Mirrored onto the outpost webhook payload under the same flag.
- Contract advertises DELTA_SUMMARY_FIELDS / DELTA_SUMMARY_ENUMS via
  gh-delta/contract and --help-json, enough to build a Zod/JSON-Schema validator.

TDD against REAL captured GraphQL payloads (test/fixtures/summaries/, recorded
from live PRs on 2026-07-11) exercised through the real fetch->normalize->
fingerprint->summary path, covering none/green/pending/failed including the
in-progress {status:IN_PROGRESS, conclusion:''} shape. Adds CLI acceptance
(none->green ci-changed) and --help-json schema tests. 211 tests pass.
@diegomarino
diegomarino merged commit c1e7aa1 into main Jul 10, 2026
3 checks passed
@diegomarino
diegomarino deleted the feat/semantic-summaries branch July 10, 2026 23:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant